package com.shinow.capacitor.plusins.printer;

import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.util.Base64;

import androidx.appcompat.app.AppCompatActivity;

import com.getcapacitor.JSArray;
import com.getcapacitor.PluginCall;
import com.shinow.capacitor.plusins.printer.zebra.ImageTransferredZpl;
import com.shinow.capacitor.plusins.printer.zebra.ZplTransferred;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;

public class Printer {
    private static final String ACTION_USB_PERMISSION = "com.android.usb.USB_PERMISSION";

    public JSArray getUsbDevices(AppCompatActivity Activity) {
        JSArray Result = new JSArray();

        UsbManager usbManager = (UsbManager) Activity.getSystemService(Context.USB_SERVICE);
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        for (String key : deviceList.keySet()) {
            Result.put(deviceList.get(key).getProductName());
        }

        return Result;
    }

    private Bitmap base64ToBitmap(String base64Data) {
        byte[] bytes = Base64.decode(base64Data, Base64.DEFAULT);
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    }

    public void printZpl(PluginCall call, AppCompatActivity Activity, String DeviceName, String Zpl) throws PrintRunTimeException {
        UsbDevice usbDevice = getUsbDevice(Activity, DeviceName);

        getUsbPermission(Activity, usbDevice, (context, intent) -> {
            UsbManager usbManager = (UsbManager) Activity.getSystemService(Context.USB_SERVICE);
            UsbDeviceConnection usbDeviceConnection = usbManager.openDevice(usbDevice);

            byte[] ZplByte = ZplTransferred.execute(Activity, Zpl).getBytes(StandardCharsets.UTF_8);
            for (int InterfaceIndex = 0, InterfaceLength = usbDevice.getInterfaceCount(); InterfaceIndex < InterfaceLength; InterfaceIndex++) {
                UsbInterface usbInterface = usbDevice.getInterface(InterfaceIndex);

                for (int EndpointIndex = 0, EndpointLength = usbInterface.getEndpointCount(); EndpointIndex < EndpointLength; EndpointIndex++) {
                    usbDeviceConnection.bulkTransfer(usbInterface.getEndpoint(EndpointIndex), ZplByte, ZplByte.length, 3000);
                }
            }

            usbDeviceConnection.close();
        }, () -> {
            call.reject("未授权设备");
        });
    }

    public void printImageBase64ToZpl(PluginCall call, AppCompatActivity Activity, String DeviceName, String Base64, int Width, int Height, int Density) throws PrintRunTimeException {
        printZpl(call, Activity, DeviceName, "^XA^PR1^MD15^PW" + Width * Density + "^LL" + Height * Density + "^LH0,0" + ImageTransferredZpl.transformationImage(base64ToBitmap(Base64)) + " ^XZ\"");
    }

    private UsbDevice getUsbDevice(AppCompatActivity Activity, String DeviceName) throws PrintRunTimeException {
        UsbManager usbManager = (UsbManager) Activity.getSystemService(Context.USB_SERVICE);
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();

        if (DeviceName == null || "".equals(DeviceName)) {
            if (deviceList.size() == 0) {
                throw new PrintRunTimeException("未连接设备");
            }

            return deviceList.get(deviceList.keySet().toArray()[0]);
        }

        for (String key : deviceList.keySet()) {
            if (DeviceName.equals(deviceList.get(key).getProductName())) {
                return deviceList.get(key);
            }
        }

        throw new PrintRunTimeException("未查找到设备");
    }

    private void getUsbPermission(AppCompatActivity Activity, UsbDevice usbDevice, UsbPermissionCallBack usbPermissionCallBack, UsbPermissionErrorCallBack usbPermissionErrorCallBack) {
        BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
            @SuppressLint("NewApi")
            public void onReceive(Context context, Intent intent) {
                if (ACTION_USB_PERMISSION.equals(intent.getAction())) {
                    synchronized (this) {
                        Activity.unregisterReceiver(this);
                        UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

                        if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false) && usbDevice.equals(device)) {
                            // 授权成功，操作USB设备
                            usbPermissionCallBack.callback(context, intent);
                        } else {
                            // 用户点击拒绝了
                            usbPermissionErrorCallBack.callback();
                        }
                    }
                }
            }
        };

        PendingIntent pendingIntent = PendingIntent.getBroadcast(Activity, 0, new Intent(ACTION_USB_PERMISSION), 0);
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        Activity.registerReceiver(broadcastReceiver, filter);
        ((UsbManager) Activity.getSystemService(Context.USB_SERVICE)).requestPermission(usbDevice, pendingIntent);
    }
}
